#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
2048 终端小游戏
支持方向键操作，彩色界面显示，无需额外依赖
"""

import os
import random
import sys
import tty
import termios
import signal

class Game2048:
    def __init__(self):
        self.size = 4
        self.board = [[0] * self.size for _ in range(self.size)]
        self.score = 0
        self.game_over = False
        
        # ANSI颜色代码
        self.colors = {
            0: "\033[48;5;235m\033[38;5;249m",      # 空格子
            2: "\033[48;5;230m\033[38;5;60m",       # 2
            4: "\033[48;5;229m\033[38;5;60m",       # 4
            8: "\033[48;5;215m\033[38;5;254m",      # 8
            16: "\033[48;5;208m\033[38;5;254m",     # 16
            32: "\033[48;5;203m\033[38;5;254m",     # 32
            64: "\033[48;5;197m\033[38;5;254m",     # 64
            128: "\033[48;5;190m\033[38;5;60m",    # 128
            256: "\033[48;5;185m\033[38;5;60m",    # 256
            512: "\033[48;5;180m\033[38;5;60m",    # 512
            1024: "\033[48;5;175m\033[38;5;254m",   # 1024
            2048: "\033[48;5;170m\033[38;5;254m",  # 2048
            'reset': "\033[0m"
        }
        
        self.init_game()
    
    def init_game(self):
        """初始化游戏，添加两个初始数字"""
        self.add_new_tile()
        self.add_new_tile()
    
    def add_new_tile(self):
        """在空位置随机添加2或4"""
        empty_cells = [(i, j) for i in range(self.size) 
                      for j in range(self.size) if self.board[i][j] == 0]
        
        if not empty_cells:
            return
        
        i, j = random.choice(empty_cells)
        self.board[i][j] = 4 if random.random() < 0.1 else 2
    
    def print_board(self):
        """打印游戏界面"""
        os.system('clear' if os.name == 'posix' else 'cls')
        
        print("\033[1;37m" + "=" * 40)
        print(f"        2048 游戏        分数: {self.score}")
        print("=" * 40 + "\033[0m")
        print()
        
        for row in self.board:
            print("+------+------+------+------+")
            print("|", end="")
            for num in row:
                color = self.colors.get(num, self.colors[2048])
                cell = str(num) if num != 0 else " "
                # 居中对齐
                cell = cell.center(6)
                print(f"{color}{cell}\033[0m", end="|")
            print()
        print("+------+------+------+------+")
        print()
        
        if self.game_over:
            print("\033[1;31m游戏结束！按 'q' 退出，按 'r' 重新开始\033[0m")
        else:
            print("\033[1;32m使用方向键移动，按 'q' 退出，按 'r' 重新开始\033[0m")
    
    def compress(self, row):
        """压缩非零元素到左边"""
        new_row = [num for num in row if num != 0]
        new_row += [0] * (self.size - len(new_row))
        return new_row
    
    def merge(self, row):
        """合并相邻相同的数字"""
        for i in range(self.size - 1):
            if row[i] != 0 and row[i] == row[i + 1]:
                row[i] *= 2
                self.score += row[i]
                row[i + 1] = 0
        return row
    
    def move_left(self):
        """向左移动"""
        moved = False
        new_board = []
        
        for row in self.board:
            compressed = self.compress(row)
            merged = self.merge(compressed)
            final = self.compress(merged)
            
            if final != row:
                moved = True
            new_board.append(final)
        
        if moved:
            self.board = new_board
            self.add_new_tile()
        return moved
    
    def move_right(self):
        """向右移动"""
        reversed_board = [row[::-1] for row in self.board]
        original = [row[:] for row in self.board]
        
        self.board = reversed_board
        moved = self.move_left()
        self.board = [row[::-1] for row in self.board]
        
        return moved
    
    def transpose(self):
        """转置矩阵"""
        self.board = [[self.board[j][i] for j in range(self.size)] 
                     for i in range(self.size)]
    
    def move_up(self):
        """向上移动"""
        self.transpose()
        moved = self.move_left()
        self.transpose()
        return moved
    
    def move_down(self):
        """向下移动"""
        self.transpose()
        reversed_board = [row[::-1] for row in self.board]
        self.board = reversed_board
        moved = self.move_left()
        self.board = [row[::-1] for row in self.board]
        self.transpose()
        return moved
    
    def can_move(self):
        """检查是否还能移动"""
        # 检查是否有空格
        for row in self.board:
            if 0 in row:
                return True
        
        # 检查是否有相邻相同的数字
        for i in range(self.size):
            for j in range(self.size - 1):
                if self.board[i][j] == self.board[i][j + 1]:
                    return True
        
        for i in range(self.size - 1):
            for j in range(self.size):
                if self.board[i][j] == self.board[i + 1][j]:
                    return True
        
        return False
    
    def check_game_over(self):
        """检查游戏是否结束"""
        self.game_over = not self.can_move()
        return self.game_over
    
    def reset_game(self):
        """重置游戏"""
        self.board = [[0] * self.size for _ in range(self.size)]
        self.score = 0
        self.game_over = False
        self.init_game()
    
    def get_input(self):
        """获取键盘输入"""
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
            
            # 处理方向键（转义序列）
            if ch == '\033':
                ch += sys.stdin.read(2)
            
            return ch
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    
    def handle_input(self, key):
        """处理输入"""
        moved = False
        
        if key.lower() == 'q':
            return False
        elif key.lower() == 'r':
            self.reset_game()
            return True
        
        # 方向键处理
        if key == '\033[A':  # 上
            moved = self.move_up()
        elif key == '\033[B':  # 下
            moved = self.move_down()
        elif key == '\033[C':  # 右
            moved = self.move_right()
        elif key == '\033[D':  # 左
            moved = self.move_left()
        
        if moved:
            self.check_game_over()
        
        return True
    
    def run(self):
        """运行游戏主循环"""
        # 设置信号处理，确保程序可以正常退出
        def signal_handler(sig, frame):
            print("\n\033[0m游戏已退出")
            sys.exit(0)
        
        signal.signal(signal.SIGINT, signal_handler)
        
        try:
            while True:
                self.print_board()
                
                if self.game_over:
                    key = self.get_input()
                    if key.lower() == 'q':
                        break
                    elif key.lower() == 'r':
                        self.reset_game()
                        continue
                
                key = self.get_input()
                if not self.handle_input(key):
                    break
        
        except KeyboardInterrupt:
            print("\n\033[0m游戏已退出")
        finally:
            # 重置终端颜色
            print("\033[0m", end="")

if __name__ == "__main__":
    game = Game2048()
    game.run()
